package com.fessc.develop.handler.processor.callback;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fessc.develop.base.Result;
import com.fessc.develop.entity.dbvo.TPayment;
import com.fessc.develop.entity.comvo.PaymentCallBackBodyVo;
import com.fessc.develop.entity.comvo.PaymentCallBackVo;
import com.fessc.develop.model.enums.EnumCallBackOption;
import com.fessc.develop.model.enums.EnumJsonProperty;
import com.fessc.develop.model.enums.EnumPaymentStatus;
import com.fessc.develop.model.enums.EnumResultType;
import com.fessc.develop.service.interfaces.ITPaymentService;
import com.fessc.develop.utils.BusiUtil;
import com.fessc.develop.utils.DateUtil;
import com.fessc.develop.utils.ErrorUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class PrePaymentCallBackProcessor implements ICallBackProcessor {

    @Resource
    private ITPaymentService paymentService;

    /**
     * 预付款交易结果回调
     *
     * @param bankCallBackVo 预付款交易结果回调报文
     * @return 返回结果
     */
    @Override
    public Result process(PaymentCallBackVo bankCallBackVo) {
        log.info("预付款回调通知处理开始");
        Result result = new Result(EnumResultType.SUCCESS.getStatusCode(), EnumResultType.SUCCESS.getMsg());
        try {
            //判断订单编号、业务类型、交易结果是否为空，是否符合报文要求
            String errorCode = check(bankCallBackVo);
            if (BusiUtil.isNotNull(errorCode)) {
                JSONObject jsonDate = new JSONObject();
                jsonDate.put(EnumJsonProperty.RES_PCSGRLT.toString(), "01");
                jsonDate.put(EnumJsonProperty.RES_FALRS.toString(), ErrorUtil.getErrorDesc(errorCode));
                result.setData(jsonDate);
                return result;
            }

            List<PaymentCallBackBodyVo> paymentList = bankCallBackVo.getSubArray();
            List<TPayment> paymentUpdateList = new ArrayList<>();
            // 组织参数批量更新
            for (PaymentCallBackBodyVo callBackBodyVo : paymentList) {
                //更新更新预付款状态
                TPayment paymentUpdate = new TPayment();
                if (BusiUtil.isEquals(callBackBodyVo.getStatus(), EnumResultType.COM_TRAN_STATUS_SUCCESS.getStatusCode())) {
                    log.info("更新预付款状态为交易成功：" + callBackBodyVo.getOrderNo());
                    paymentUpdate.setSuborderno(callBackBodyVo.getOrderNo());
                    paymentUpdate.setPaymentStatus(EnumPaymentStatus.PAYMENT_SUCCESS.toString()); //银行扣款成功
                    paymentUpdate.setPaymentLog(EnumPaymentStatus.PAYMENT_SUCCESS_LOG.toString());
                    paymentUpdate.setBankRefids(callBackBodyVo.getBankReference());
                    paymentUpdate.setPaymentBatchNo(bankCallBackVo.getBatchSerialNo());
                    if (BusiUtil.isNotNull(callBackBodyVo.getCoreTranTime()) && callBackBodyVo.getCoreTranTime().length() == 14) {
                        paymentUpdate.setPaymentWorkdate(DateUtil.dateToString(DateUtil.stringToDateTime(callBackBodyVo.getCoreTranTime()), DateUtil.DATE_TIME_FORMAT));  //银行扣款时间
                    }
                    paymentUpdateList.add(paymentUpdate);
                } else if (BusiUtil.isEquals(callBackBodyVo.getStatus(), EnumResultType.COM_TRAN_STATUS_FAIL.getStatusCode())) {
                    log.info("更新预付款状态为交易失败：" + callBackBodyVo.getOrderNo());
                    paymentUpdate.setSuborderno(callBackBodyVo.getOrderNo());
                    paymentUpdate.setPaymentStatus(BusiUtil.nvl(callBackBodyVo.getFailCode(), EnumPaymentStatus.PAYMENT_FAIL.toString())); //银行扣款失败败
                    paymentUpdate.setPaymentLog(BusiUtil.nvl(callBackBodyVo.getDescription(), EnumPaymentStatus.PAYMENT_FAIL_LOG.toString()));
                    paymentUpdate.setPaymentBatchNo(bankCallBackVo.getBatchSerialNo());
                    paymentUpdateList.add(paymentUpdate);
                } else {
                    log.info("预付款状态为处理中，不更新交易状态：" + callBackBodyVo.getOrderNo());
                }
            }
            // 批量更新交易状态
            if (!paymentUpdateList.isEmpty()) {
                paymentService.updatePrePaymentStatusByOrderNo(paymentUpdateList);
            }
            JSONObject jsonDate = new JSONObject();
            jsonDate.put(EnumJsonProperty.RES_PCSGRLT.toString(), EnumResultType.COM_RES_SUCCESS.getStatusCode());
            jsonDate.put(EnumJsonProperty.RES_FALRS.toString(), EnumResultType.COM_RES_SUCCESS.getMsg());
            result.setData(jsonDate);
            // 返回响应报文
            log.info("预付款回调通知处理结束，返回报文：" + JSON.toJSONString(result));
            return result;
        } catch (Exception e) {
            log.info("预付款回调通知处理异常：" + e.getMessage());
            JSONObject jsonDate = new JSONObject();
            jsonDate.put(EnumJsonProperty.RES_PCSGRLT.toString(), EnumResultType.COM_RES_FAIL.getStatusCode());
            jsonDate.put(EnumJsonProperty.RES_FALRS.toString(), BusiUtil.nvl(e.getMessage(), EnumResultType.COM_RES_FAIL.getMsg()));
            result.setData(jsonDate);
            // 返回响应报文
            return result;
        }
    }

    private String check(PaymentCallBackVo bankCallBackVo) {
        // 校验业务操作类型
        if (BusiUtil.isNull(bankCallBackVo.getOption())) {
            return "EE1027";
        }
        if (BusiUtil.isNull(bankCallBackVo.getSubArray())) {
            return "EE1028";
        }
        if (BusiUtil.isNotEquals(bankCallBackVo.getOption(), "1") &&
                BusiUtil.isNotEquals(bankCallBackVo.getOption(), "2") &&
                BusiUtil.isNotEquals(bankCallBackVo.getOption(), "3")) {
            return "EE1007";
        }

        List<String> orders = bankCallBackVo.getSubArray().stream().map(PaymentCallBackBodyVo::getOrderNo).collect(Collectors.toList());
        List<TPayment> paymentList = paymentService.getPaymentBySubOrderNoAndPayStatus(orders, "");
        // 校验明细 子订单号 + 状态 查询，少于总数，也报错
        if (BusiUtil.isNull(orders) || orders.isEmpty()) {
            return "EE1010";
        }
        return "";
    }

    @Override
    public String getOption() {

        return EnumCallBackOption.PRE_PAYMENT_CALL_BACK.toString();
    }
}
